package com.sdhs.costcontrol.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import com.sdhs.util.BidUtilization;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.sdhs.businessfile.domain.BusinessFile;
import com.sdhs.businessfile.service.IBusinessFileService;
import com.sdhs.common.enums.BusinessTypeEnum;
import com.sdhs.common.utils.DateUtils;
import com.sdhs.common.utils.SecurityUtils;
import com.sdhs.costcontrol.domain.ControlContract;
import com.sdhs.costcontrol.domain.GcControlContractPay;
import com.sdhs.costcontrol.mapper.GcControlContractPayMapper;
import com.sdhs.costcontrol.service.IGcControlContractPayService;

import cn.hutool.core.collection.CollectionUtil;

/**
 * 合同支付跟踪Service业务层处理
 * 
 * @author wanglei
 * @date 2025-03-14
 */
@Service
public class GcControlContractPayServiceImpl implements IGcControlContractPayService 
{
    @Autowired
    private GcControlContractPayMapper gcControlContractPayMapper;
    
    @Autowired
    private IBusinessFileService businessFileService;

    /**
     * 查询合同支付跟踪
     * 
     * @param id 合同支付跟踪主键
     * @return 合同支付跟踪
     */
    @Override
    public GcControlContractPay selectGcControlContractPayById(Long id)
    {
    	GcControlContractPay controlContractPay = gcControlContractPayMapper.selectGcControlContractPayById(id);
    	List<BusinessFile> fileList = businessFileService.listByBusinessTypeAndId(BusinessTypeEnum.GC_CONTROL_CONTRACT_PAY.getCode(), String.valueOf(id));
    	controlContractPay.setFileList(fileList);
    	return controlContractPay;
    }
	/**
	 * 根据项目id和合同id查询累计数据
	 *
	 * @param projectId 项目id
	 * @param contractId 合同id
	 * @return 合同支付跟踪
	 */
	@Override
	public GcControlContractPay selectControlContractPayByProjectId(Long projectId,String contractId)
	{
		return gcControlContractPayMapper.selectControlContractPayByProjectId(projectId,contractId);
	}
    /**
     * 查询合同支付跟踪列表
     * 
     * @param gcControlContractPay 合同支付跟踪
     * @return 合同支付跟踪
     */
    @Override
    public ControlContract selectGcControlContractPayList(GcControlContractPay gcControlContractPay)
    {
    	// 查询出主合同/支付的树形结构
    	List<ControlContract> list = gcControlContractPayMapper.selectGcControlContractPayList(gcControlContractPay);
    	ControlContract controlContract = new ControlContract();
    	if (CollectionUtil.isNotEmpty(list)) {
    		controlContract.setChildren(list);
    		// 取出主合同编号
    		List<String> originalContractNumList = list.stream().map(contract -> contract.getContractNumber()).collect(Collectors.toList());
    		// 根据主合同编号查询其下最新的子合同
    		List<ControlContract> allSubContractList = gcControlContractPayMapper.selectSubContract(originalContractNumList);
    		for (ControlContract contract : list) {
    			BigDecimal contractMoneyUpdate = contract.getContractMoney();
    			contract.setMainContractId(contract.getContractId());
    			List<ControlContract> subContractList = allSubContractList.stream().filter(
    					subContract -> subContract.getOriginalContractNum().equals(contract.getContractNumber())).collect(Collectors.toList());
    			ControlContract subContract = null;
    			if (CollectionUtil.isNotEmpty(subContractList)) {
    				// 有子合同
    				subContract = subContractList.get(0);
    				subContract.setMainContractId(contract.getContractId());
    				if (contractMoneyUpdate == null) {
    					subContract.setContractMoney(subContract.getMoney());
    				} else {
    					subContract.setContractMoney(contractMoneyUpdate);
    				}
    				contract.setContractMoney(contract.getMoney());
    			} else {
    				// 没有子合同
    				if (contractMoneyUpdate == null) {
    					contract.setContractMoney(contract.getMoney());
    				}
    			}
    			List<GcControlContractPay> payList = contract.getPayList();
    			if (CollectionUtil.isNotEmpty(payList)) {
    				// 累计支付金额
    				BigDecimal totalPaymentAmount = 
    						payList.stream().map(GcControlContractPay::getThisPaymentAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
    				// 累计支付比例
    				BigDecimal totalPaymentRatio = 
    						payList.stream().map(GcControlContractPay::getThisPaymentRatio).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
    				// 累计发票金额
    				BigDecimal totalInvoiceAmount = 
    						payList.stream().map(GcControlContractPay::getThisInvoiceAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
    				// 累计发票比例
    				BigDecimal totalInvoiceRatio = 
    						payList.stream().map(GcControlContractPay::getThisInvoiceRatio).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
					//累计 已开票金额（不含税）
					BigDecimal totalNotInvoicedAmount =
    						payList.stream().map(GcControlContractPay::getNotInvoicedAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);

					//累计 未开发票金额（含税）
					BigDecimal totalUninvoicedAmount =
							payList.stream().map(GcControlContractPay::getUninvoicedAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);

					//累计 未开发票比例（含税）
					BigDecimal totalProportionUnissuedInvoices =
							payList.stream().map(GcControlContractPay::getProportionUnissuedInvoices).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);

					//累计 成本确认金额(不含税支出类合同)
					BigDecimal totalNotCostConfirmationAmount =
							payList.stream().map(GcControlContractPay::getNotCostConfirmationAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);


					//累计 成本确认金额(支出类合同)
					BigDecimal totalCostConfirmationAmount =
							payList.stream().map(GcControlContractPay::getCostConfirmationAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);

					//累计 成本确认比例(支出类合同)
					BigDecimal totalCostConfirmationRatio =
							payList.stream().map(GcControlContractPay::getCostConfirmationRatio).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);

					//累计 应付账款(支出类合同)
					BigDecimal totalAccountsPayable =
							payList.stream().map(GcControlContractPay::getAccountsPayable).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
    				if (subContract != null) {
    					subContract.setTotalPaymentAmount(totalPaymentAmount);
    					subContract.setTotalPaymentRatio(totalPaymentRatio);
    					subContract.setTotalInvoiceAmount(totalInvoiceAmount);
    					subContract.setTotalInvoiceRatio(totalInvoiceRatio);
						subContract.setTotalNotInvoicedAmount(totalNotInvoicedAmount);
						subContract.setTotalUninvoicedAmount(totalUninvoicedAmount);
						subContract.setTotalProportionUnissuedInvoices(totalProportionUnissuedInvoices);
						subContract.setTotalNotCostConfirmationAmount(totalNotCostConfirmationAmount);
						subContract.setTotalCostConfirmationAmount(totalCostConfirmationAmount);
						subContract.setTotalCostConfirmationRatio(totalCostConfirmationRatio);
						subContract.setTotalAccountsPayable(totalAccountsPayable);
    					subContract.setPayList(payList);
    					contract.setChildren(subContractList);
    					contract.setPayList(null);
    					contract.setContractMoneyTemp(subContract.getContractMoney());
    				} else {
    					contract.setTotalPaymentAmount(totalPaymentAmount);
        				contract.setTotalPaymentRatio(totalPaymentRatio);
        				contract.setTotalInvoiceAmount(totalInvoiceAmount);
        				contract.setTotalInvoiceRatio(totalInvoiceRatio);
						contract.setTotalNotInvoicedAmount(totalNotInvoicedAmount);
						contract.setTotalUninvoicedAmount(totalUninvoicedAmount);
						contract.setTotalProportionUnissuedInvoices(totalProportionUnissuedInvoices);
						contract.setTotalNotCostConfirmationAmount(totalNotCostConfirmationAmount);
						contract.setTotalCostConfirmationAmount(totalCostConfirmationAmount);
						contract.setTotalCostConfirmationRatio(totalCostConfirmationRatio);
						contract.setTotalAccountsPayable(totalAccountsPayable);
        				contract.setContractMoneyTemp(contract.getContractMoney());
    				}
    				contract.setTotalPaymentAmountTemp(totalPaymentAmount);
    				contract.setTotalInvoiceAmountTemp(totalInvoiceAmount);
    			} else {
    				if (subContract != null) {
    					subContract.setTotalPaymentAmount(BigDecimal.ZERO);
    					subContract.setTotalPaymentRatio(BigDecimal.ZERO);
    					subContract.setTotalInvoiceAmount(BigDecimal.ZERO);
    					subContract.setTotalInvoiceRatio(BigDecimal.ZERO);
    					subContract.setTotalNotInvoicedAmount(BigDecimal.ZERO);
						subContract.setTotalUninvoicedAmount(BigDecimal.ZERO);
						subContract.setTotalProportionUnissuedInvoices(BigDecimal.ZERO);
						subContract.setTotalNotCostConfirmationAmount(BigDecimal.ZERO);
						subContract.setTotalCostConfirmationAmount(BigDecimal.ZERO);
						subContract.setTotalCostConfirmationRatio(BigDecimal.ZERO);
						subContract.setTotalAccountsPayable(BigDecimal.ZERO);
    					contract.setChildren(subContractList);
    					contract.setContractMoneyTemp(subContract.getContractMoney());
    				} else {
    					contract.setTotalPaymentAmount(BigDecimal.ZERO);
	    				contract.setTotalPaymentRatio(BigDecimal.ZERO);
	    				contract.setTotalInvoiceAmount(BigDecimal.ZERO);
	    				contract.setTotalInvoiceRatio(BigDecimal.ZERO);
	    				contract.setTotalNotInvoicedAmount(BigDecimal.ZERO);
						contract.setTotalUninvoicedAmount(BigDecimal.ZERO);
						contract.setTotalProportionUnissuedInvoices(BigDecimal.ZERO);
						contract.setTotalNotCostConfirmationAmount(BigDecimal.ZERO);
						contract.setTotalCostConfirmationAmount(BigDecimal.ZERO);
						contract.setTotalCostConfirmationRatio(BigDecimal.ZERO);
						contract.setTotalAccountsPayable(BigDecimal.ZERO);
	    				contract.setContractMoneyTemp(contract.getContractMoney());
    				}
    			}
    		}
    		// 合同总金额
    		BigDecimal allContractMoney = 
    				list.stream().map(ControlContract::getContractMoneyTemp).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
    		controlContract.setContractMoney(allContractMoney);
    		// 累计支付金额
    		BigDecimal allPaymentAmount = 
    				list.stream().map(ControlContract::getTotalPaymentAmountTemp).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
    		controlContract.setTotalPaymentAmount(allPaymentAmount);
    		// 累计发票金额
    		BigDecimal allInvoiceAmount = 
    				list.stream().map(ControlContract::getTotalInvoiceAmountTemp).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
    		controlContract.setTotalInvoiceAmount(allInvoiceAmount);
    		// 累计支付比例
    		BigDecimal allPaymentRatio = null;
    		// 累计发票比例
    		BigDecimal totalInvoiceRatio = null;
    		if (BigDecimal.ZERO.compareTo(allContractMoney) == 0) {
    			allPaymentRatio = BigDecimal.ZERO;
    			totalInvoiceRatio = BigDecimal.ZERO;
    		} else {
    			allPaymentRatio = allPaymentAmount.multiply(new BigDecimal("100")).divide(allContractMoney, 2, RoundingMode.HALF_UP);
    			totalInvoiceRatio = allInvoiceAmount.multiply(new BigDecimal("100")).divide(allContractMoney, 2, RoundingMode.HALF_UP);
    		}
    		controlContract.setTotalPaymentRatio(allPaymentRatio);
    		controlContract.setTotalInvoiceRatio(totalInvoiceRatio);
    	}
        return controlContract;
    }

    /**
     * 新增合同支付跟踪
     * 
     * @param gcControlContractPay 合同支付跟踪
     * @return 结果
     */
    @Override
    public int insertGcControlContractPay(GcControlContractPay gcControlContractPay)
    {
		gcControlContractPay.setCreater(SecurityUtils.getUsername());
        gcControlContractPay.setCreateTime(DateUtils.getNowDate());
        int result = gcControlContractPayMapper.insertGcControlContractPay(gcControlContractPay);
        businessFileService.saveFileBatch(BusinessTypeEnum.GC_CONTROL_CONTRACT_PAY.getCode(), String.valueOf(gcControlContractPay.getId()), gcControlContractPay.getFileList());
		/*新增合同支付的时候计算我的项目-利润率测试-实施期利润率*/
		BidUtilization.UpdateBidUtilization(gcControlContractPay.getProjectId());
		/*新增合同支付的时候-调用修改我的项目-中间表合同表支付数据*/
		BidUtilization.UpdateMyProjectContract(gcControlContractPay.getProjectId(), gcControlContractPay.getContractId());
		return result;
    }

    /**
     * 修改合同支付跟踪
     * 
     * @param gcControlContractPay 合同支付跟踪
     * @return 结果
     */
    @Override
    public int updateGcControlContractPay(GcControlContractPay gcControlContractPay)
    {
		gcControlContractPay.setUpdater(SecurityUtils.getUsername());
        gcControlContractPay.setUpdateTime(DateUtils.getNowDate());
        int result = gcControlContractPayMapper.updateGcControlContractPay(gcControlContractPay);
        businessFileService.saveFileBatch(BusinessTypeEnum.GC_CONTROL_CONTRACT_PAY.getCode(), String.valueOf(gcControlContractPay.getId()), gcControlContractPay.getFileList());
		/*修改合同支付的时候计算我的项目-利润率测试-实施期利润率*/
		BidUtilization.UpdateBidUtilization(gcControlContractPay.getProjectId());
		/*修改合同支付的时候-调用修改我的项目-中间表合同表支付数据*/
		BidUtilization.UpdateMyProjectContract(gcControlContractPay.getProjectId(), gcControlContractPay.getContractId());
		return result;
    }

    /**
     * 批量删除合同支付跟踪
     * 
     * @param ids 需要删除的合同支付跟踪主键
     * @return 结果
     */
    @Override
    public int deleteGcControlContractPayByIds(Long[] ids)
    {
		Long projectId = null;
		String  contractId = null;
		if (ids != null && ids.length > 0) {
			GcControlContractPay gcControlContractPay = gcControlContractPayMapper.selectGcControlContractPayById(ids[0]);
			projectId = gcControlContractPay.getProjectId();
			contractId = gcControlContractPay.getContractId();
		}
		 int i = gcControlContractPayMapper.deleteGcControlContractPayByIds(ids);
		/*删除合同支付的时候计算我的项目-利润率测试-实施期利润率*/
		BidUtilization.UpdateBidUtilization(projectId);
		/*删除合同支付的时候-调用修改我的项目-中间表合同表支付数据*/
		BidUtilization.UpdateMyProjectContract(projectId, contractId);
		return i;
    }

    /**
     * 删除合同支付跟踪信息
     * 
     * @param id 合同支付跟踪主键
     * @return 结果
     */
    @Override
    public int deleteGcControlContractPayById(Long id)
    {
        return gcControlContractPayMapper.deleteGcControlContractPayById(id);
    }
}
